<template>
  <div class="container">
    <div>
      <el-steps :active="step" align-center>
        <el-step title="上传图像及CSV/XLSX文件" icon="el-icon-link"></el-step>
        <el-step title="点击'开始识别'按钮" icon="el-icon-search"></el-step>
        <el-step title="生成图片描述" icon="el-icon-edit"></el-step>
        <el-step title="预览/下载识别完成文件" icon="el-icon-finished"></el-step>
      </el-steps>
    </div>

    <div class="main-box">
      <div class="upload-area">
        <div class="upload-img">
          <div class="tips">
            <img src="../assets/image/upload_img.png" alt="" class="tips-icon"/>
            <div class="tips-text">在此处上传全部眼底图像</div>
          </div>
          <el-upload
              drag
              action="/"
              multiple
              accept=".jpg,.jpeg,.png"
              :show-file-list="false"
              :auto-upload="false"
              :file-list="imgFileList"
              :on-change="handleImageUploadChange"
          >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">将全部图像拖到此处或批量上传，随后<em>点击下方'上传完毕'按钮</em></div>
            <div class="el-upload__tip" slot="tip"
             style="display: flex; align-items: center;justify-content: space-between">
              只能上传jpg/png文件，请勿上传太多较大图像，否则会导致处理时间太长。
              <el-button type="success" size="mini" @click="batchUpload">上传完毕</el-button>
            </div>
          </el-upload>
        </div>

        <div class="blank">
          <el-divider><i class="el-icon-upload" style="font-size: 20px"></i></el-divider>
        </div>

        <div class="upload-csv">
          <div class="tips">
            <img src="../assets/image/upload_csv.png" alt="" class="tips-icon"/>
            <div class="tips-text">在此处上传CSV/XLSX文件</div>
          </div>
          <el-upload
              drag
              action="https://yiyuy.mynatapp.cc/model/uploadCsv"
              :on-exceed="handleCsvExceed"
              :on-remove="handleCsvRemove"
              :on-progress="handleCsvProgress"
              :on-success="handleCsvSuccess"
              :on-error="handleError"
              accept=".csv,.xlsx"
              :limit="1"
          >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">将CSV/XLSX文件拖到此处，或<em>点击上传</em></div>
            <div class="el-upload__tip" slot="tip">只能上传CSV/XLSX文件</div>
          </el-upload>
        </div>
      </div>

      <div class="divider">
        <el-divider></el-divider>
      </div>

      <div class="result-area">
        <div class="tips">
          <img src="../assets/image/model_pred.png" alt="" class="tips-icon"/>
          <div class="tips-text">模型预测结果预览</div>
          <div class="warning">
            <el-tooltip class="item" effect="dark"
                        placement="top">
              <div slot="content">如需下载CSV文件，请看右侧<br/>下载后的CSV文件将与上传时的格式保持一致，同时多出8列模型预测结果</div>
              <i class="el-icon-warning keywords-icon"></i>
            </el-tooltip>
          </div>
          <div class="middle-tips">
            <div class="normal-text">tips：以下结果是在阈值为0.8的情况下得出的</div>
            <el-tooltip class="item" effect="dark"
                        placement="top">
              <div slot="content">模型会为每种疾病预测一个得分，规定当得分>阈值，则该病值为1，即患病，否则相反。</div>
              <div class="tooltip-text">(什么是阈值?)</div>
            </el-tooltip>
          </div>
          <div class="download-tip">
            <el-link type="info" :underline="false">需要下载识别后的CSV文件？</el-link>
            <el-link type="primary" :underline="false" @click="downloadCsvFile">点击这里</el-link>
          </div>
        </div>
        <el-table
            :data="predTableData"
            style="width: 100%"
            border
            stripe
            max-height="400"
        >
          <el-table-column
              fixed
              prop="leftFundus"
              label="左眼文件"
              width="200px">
            <template slot-scope="scope">
              <img :src="scope.row.leftFundus" alt="" style="width: 100%;height: 100%"/>
            </template>
          </el-table-column>
          <el-table-column
              fixed
              prop="rightFundus"
              label="右眼文件"
              width="200px">
            <template slot-scope="scope">
              <img :src="scope.row.rightFundus" alt="" style="width: 100%;height: 100%"/>
            </template>
          </el-table-column>
          <el-table-column
              fixed
              prop="N"
              label="N"
              width="130px">
          </el-table-column>
          <el-table-column
              fixed
              prop="D"
              label="D"
              width="130px">
          </el-table-column>
          <el-table-column
              fixed
              prop="G"
              label="G"
              width="130px">
          </el-table-column>
          <el-table-column
              fixed
              prop="C"
              label="C"
              width="130px">
          </el-table-column>
          <el-table-column
              fixed
              prop="A"
              label="A"
              width="130px">
          </el-table-column>
          <el-table-column
              fixed
              prop="H"
              label="H"
              width="130px">
          </el-table-column>
          <el-table-column
              fixed
              prop="M"
              label="M"
              width="130px">
          </el-table-column>
          <el-table-column
              fixed
              prop="O"
              label="O"
              width="130px">
          </el-table-column>
        </el-table>
      </div>

      <div class="submit-btn">
        <el-button type="primary" round @click="startDiagnosis">开始识别<i class="el-icon-check"></i></el-button>
      </div>
    </div>
  </div>
</template>

<script>
import {getBatchProbList, getMatchFileList} from "@/api/diagnosis";
import axios from "axios";
import {io} from "socket.io-client";

export default {
  name: "BatchDiagnosis",
  data() {
    return {
      step: 0,
      socket: null,
      // 随即切换内容定时器
      randomChangeTextId: null,
      // 全局加载
      loading: null,
      // 统计预测完成了几个
      count: 0,
      predTableData: [
        {
          leftFundus: 'https://service-plat.oss-cn-beijing.aliyuncs.com/1_right.jpg',
          rightFundus: 'https://service-plat.oss-cn-beijing.aliyuncs.com/1_left.jpg',
          N: '暂无',
          D: '暂无',
          G: '暂无',
          C: '暂无',
          A: '暂无',
          H: '暂无',
          M: '暂无',
          O: '暂无'
        }
      ],
      imgFileList: [],
      csvFilename: '',
    }
  },
  beforeDestroy() {
    // 离开时断开Socketio连接
    if (this.socket !== null) {
      console.log('断开连接')
      this.socket.disconnect();
    }
  },
  mounted() {
    this.initSocket();
  },
  methods: {
    initSocket() {
      this.socket = io('https://yiyuy.mynatapp.cc/model', {
        transports: ['websocket']
      })

      this.socket.on('disconnect', (msg) => {
        this.socket.disconnect()
      })

      // 监听服务器那边返回的消息
      this.socket.on('batch_diagnosis_response', (data) => {
        this.count ++;
        if ( data === '[OVER]' ) {
          this.step = 4;
          this.loading.close();

          // 关闭定时器
          if ( this.randomChangeTextId !== undefined ) {
            clearInterval(this.randomChangeTextId)
          }

          this.$message.success('批量诊断完毕')
        }else {
          this.step = 3;
          let table = document.querySelector('.result-area')
          table.style.opacity = 1;
          data.leftFundus = 'data:image/jpeg;base64,' + data.leftFundus
          data.rightFundus = 'data:image/jpeg;base64,' + data.rightFundus

          this.predTableData.push(data)
        }
      })
    },
    // 图像上传时内容改变调用的函数
    handleImageUploadChange(fileList) {
      this.imgFileList.push(fileList)
    },
    // CSV超出时调用的函数
    handleCsvExceed(files, fileList) {
      this.$message.error('最多只能上传一个CSV/XLSX文件')
    },
    handleCsvRemove(files, fileList) {
      this.step = 0;
      this.$message.success('文件移除成功')
    },
    handleCsvProgress(event, files, fileList){
      this.$message.warning('文件上传中...')
    },
    handleCsvSuccess(response, file, fileList) {
      this.step = 1;
      if ( response.code !== 200 ) {
        return this.$message.error(response.msg)
      }
      this.csvFilename = response.data;
      this.$message.success('文件上传成功')
    },
    handleError(err, file, fileList) {
      this.$message.error('文件上传失败')
    },
    // 批量上传图像
    batchUpload() {
      if ( this.imgFileList.length === 0 ) {
        this.$message.warning('请先上传图像文件')
        return
      }

      let formData = new FormData()
      // 传文件数组 循环append
      for ( let i = 0 ; i < this.imgFileList.length ; i ++ ) {
        formData.append('files', this.imgFileList[i].raw)
      }
      // 上传到服务器
      axios.post('https://yiyuy.mynatapp.cc/model/uploadBatchImage', formData, {
        headers: { "Content-Type": "multipart/form-data" }
      }).then(response => {
        this.$message.success("文件上传成功！");
      }).catch(error => {
        this.$message.error("文件上传失败！");
        console.error(error);
      });

      // 除此之外 上传到AUTODL
      axios.post('/llava/uploadBatchImage', formData, {
        headers: { "Content-Type": "multipart/form-data" }
      })
    },
    // 下载csv文件
    downloadCsvFile() {
      if ( this.csvFilename === '' ) {
        this.$message.warning('请先上传CSV/XLSX文件')
        return
      }
      // 创建一个隐藏的<a>元素
      let link = document.createElement('a');
      link.style.display = 'none';
      document.body.appendChild(link);

      // 通过 Flask 的路由来获取文件路径
      link.href = 'https://yiyuy.mynatapp.cc/model/downloadCsv?filename=' + this.csvFilename;
      link.download = this.csvFilename;

      // 模拟点击事件来触发文件下载
      link.click();

      // 移除创建的<a>元素
      document.body.removeChild(link);
    },
    // 开始批量诊断
    startDiagnosis() {
      if ( this.csvFilename === '' ) {
        this.$message.warning('请先上传CSV/XLSX文件')
        return
      }

      // 调用后端接口获取诊断结果
      this.step = 2;

      // 做一个过度
      let loadingText = 'LLAVA与模型正在努力工作中...'
      // 0.开启整页加载
      this.loading = this.$loading({
        lock: true,
        text: loadingText,
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });

      let randomText = [
          '你知道吗?其实所使用的多模态网络在其他领域也很强!',
          '人眼只能感知红，绿，蓝三种颜色，其他颜色都是这三种颜色叠加出来的。',
          '小知识：传入大脑的视觉信息都是倒着的哦。',
          '一个指纹平均有40个特征识别区，而虹膜上却有256个，因此更适合用于保密设定。',
          '每只眼睛都有一个小小的盲点，视神经从这里穿过，之所以我们感觉不到是因为另一只眼睛的代偿作用',
          '大多数人认为眼泪是水，实际上它是由脂肪、黏液和水共同组成的',
      ]

      // 每5秒钟 切换一次整页加载的文本
      let that = this;
      setTimeout(() => {
        that.randomChangeTextId = setInterval(() => {
          let index = Math.floor(Math.random() * randomText.length)
          loadingText = randomText[index]
          that.loading.setText(loadingText)
        },5000)
      },5000)

      // 1.隐藏分割线
      let line = document.querySelector('.divider')
      line.style.opacity = 0

      // 2.隐藏表格
      let table = document.querySelector('.result-area')
      table.style.opacity = 0;

      this.predTableData = []

      this.socket.emit('startBatchDiagnosis', {'csvFilename': this.csvFilename});

      // 1s后 还原分割线
      setTimeout(() => {
        line.style.opacity = 1;
      },1000)

    }
  },
}
</script>

<style lang="less" scoped>
@keyframes MoveIn {
  0% {
    opacity: 0;
    transform: translateY(12px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  animation: MoveIn .7s cubic-bezier(.4, 0, .2, 1);
  padding-top: 10px;

  .main-box {
    width: 100%;
    margin-top: 2%;
    padding-left: 5px;
    padding-right: 5px;

    .upload-area {
      width: 100%;
      display: flex;
      justify-content: center;
      .blank {
        width: 25%;
        display: flex;
        align-items: center;
      }

      .upload-img {
        width: 35%;
      }

      .upload-csv {
        width: 35%;
        float: right;
      }

      /deep/ .el-upload {
        width: 100%;
      }

      /deep/ .el-upload .el-upload-dragger {
        width: 100%;
      }
    }

    .divider {
      opacity: 1;
      transition: all 0.5s;
    }

    .result-area {
      opacity: 1;
      transition: all 0.5s;
    }

    .submit-btn {
      margin: 10px auto;
      width: 12%;
    }
  }

  .tips {
    width: 100%;
    display: flex;
    align-items: center;
    position: relative;

    .tips-icon {
      width: 20px;
      height: 20px;
    }

    .tips-text {
      font-size: 14px;
      font-weight: bold;
    }

    .middle-tips {
      margin: 0 auto;
      display: flex;
      align-items: center;
      .normal-text {
        font-size: 12px;
        font-weight: bold;
      }

      .tooltip-text {
        font-size: 11px;
        color: #999;
        text-underline: #606266;
      }
    }

    .download-tip{
      position: absolute;
      right: 10px;
    }
  }
}
</style>